﻿using System;
using System.Collections.Generic;
using System.Linq;
using Kugar.Core.ExtMethod;
using Kugar.Web.Wechat.Entities;
using Kugar.Web.Wechat.Enums;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using JsonReader = Newtonsoft.Json.JsonReader;
using JsonWriter = Newtonsoft.Json.JsonWriter;

namespace Kugar.Web.Wechat.Serializers
{
    public class WxMessageNewtonsoftJsonSerializer : JsonConverter
    {
        private static HashSet<Type> _checkTypes = new HashSet<Type>()
        {
            typeof (WxMessageBase),
            typeof (WxMessage_Text),
            typeof (WxMessage_Image),
            typeof (WxMessage_Video),
            typeof (WxMessage_Voice),
            typeof (WxMessage_News)

        };

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var tmp = (WxMessageBase) value;

            writer.WriteStartObject();
            writer.WriteProperty("ToUserOpenID", tmp.ToUserOpenID);
            writer.WriteProperty("MsgType", (int) tmp.MsgType);
            if (tmp is WxMessage_Text)
            {
                var v = (WxMessage_Text) tmp;
                writer.WriteProperty("Text", v.Text);
            }
            else if (tmp is WxMessage_Image)
            {
                var v = (WxMessage_Image) tmp;
                writer.WriteProperty("MediaID", v.MediaID);
            }
            else if (tmp is WxMessage_Video)
            {
                var v = (WxMessage_Video) tmp;
                writer.WriteProperty("MediaID", v.MediaID);
                writer.WriteProperty("Thumb_media_id", v.Thumb_media_id);
                writer.WriteProperty("Title", v.Title);
                writer.WriteProperty("Description", v.Description);
            }
            else if (tmp is WxMessage_Voice)
            {
                var v = (WxMessage_Voice) tmp;
                writer.WriteProperty("MediaID", v.MediaID);
            }
            else if (tmp is WxMessage_News)
            {
                var v = (WxMessage_News) tmp;
                writer.WritePropertyName("Articles");
                writer.WriteStartArray();
                foreach (var article in v.Articles)
                {
                    serializer.Serialize(writer, article);
                }
                writer.WriteEndArray();
            }


            writer.WriteEndObject();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
            JsonSerializer serializer)
        {
            var json = (JObject) JObject.ReadFrom(reader);

            var msgType = (WxMessageMsgTypeEnum) json.GetInt("MsgType");
            WxMessageBase result = null;
            switch (msgType)
            {
                case WxMessageMsgTypeEnum.Text:
                    result = new WxMessage_Text()
                    {
                        Text = json.GetString("Text"),
                    };
                    break;
                case WxMessageMsgTypeEnum.Image:
                    result = new WxMessage_Image()
                    {
                        MediaID = json.GetString("MediaID")
                    };
                    break;
                case WxMessageMsgTypeEnum.Voice:
                    result = new WxMessage_Voice()
                    {
                        MediaID = json.GetString("MediaID"),
                    };
                    break;
                case WxMessageMsgTypeEnum.Video:
                    result = new WxMessage_Video()
                    {
                        MediaID = json.GetString("MediaID"),
                        Thumb_media_id = json.GetString("Thumb_media_id"),
                        Title = json.GetString("Title"),
                        Description = json.GetString("Description")
                    };
                    break;
                case WxMessageMsgTypeEnum.News:
                    result = new WxMessage_News()
                    {
                        Articles =
                            json.GetJObjectArray("Articles")
                                .Select(p => p.ToObject<WxMessage_News.NewsItem>())
                                .ToArrayEx()
                    };
                    break;

            }
            if (result != null)
            {
                result.ToUserOpenID = json.GetString("ToUserOpenID");
            }

            return result;
        }

        public override bool CanConvert(Type objectType)
        {
            return _checkTypes.Contains(objectType);
        }
    }

}
